﻿/***********************************************************************
 * CLR 版本: 4.0.30319.225
 * 工程名称: $projectname$
 * 命名空间: Toulr.Util.Geography
 * 文件名称: PointDouble
 * 描    述: 
 * 作    者: 18901309129@189.cn
 * 登录用户: hyyu
 * 创建时间: 2011-6-14 18:56:10
 * 创建年份: 2011
 * Update History: 
 ***********************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;

namespace Toulr.Util.Geography
{
    /// <summary>
    /// 使用直角坐标表示平面上的点，数值使用double类型
    /// </summary> 
    public struct PointDouble
    {
        /// <summary>
        /// 表示没有实际值的PointDouble实例
        /// </summary>
        public static readonly PointDouble Empty;

        static PointDouble()
        {
            Empty = new PointDouble(double.NaN, double.NaN);
        }

        private double x;
        private double y;

        /// <summary>
        /// 用指定的坐标初始化<see cref="PointDouble"/>的实例
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public PointDouble(double x, double y)
        {
            this.x = x;
            this.y = y;
        }

        [Browsable(false)]
        public bool IsEmpty
        {
            get
            {
                return ((x == Empty.x) && (y == Empty.y));
            }
        }

        /// <summary>
        /// 获取或设置横坐标的值
        /// </summary>
        public double X
        {
            get { return x; }
            set { x = value; }
        }

        /// <summary>
        /// 获取或设置纵坐标的值
        /// </summary>
        public double Y
        {
            get { return y; }
            set { y = value; }
        }

        public static PointDouble operator +(PointDouble pt, Size sz)
        {
            return Add(pt, sz);
        }

        public static PointDouble operator -(PointDouble pt, Size sz)
        {
            return Subtract(pt, sz);
        }

        public static PointDouble operator +(PointDouble pt, SizeDouble sz)
        {
            return Add(pt, sz);
        }

        public static PointDouble operator -(PointDouble pt, SizeDouble sz)
        {
            return Subtract(pt, sz);
        }

        public static bool operator ==(PointDouble left, PointDouble right)
        {
            return ((left.X == right.X) && (left.Y == right.Y));
        }

        public static bool operator !=(PointDouble left, PointDouble right)
        {
            return !(left == right);
        }

        /// <summary>
        /// 在指定的点的基础上平移
        /// </summary>
        /// <param name="pt">The <see cref="PointDouble"/> to translate.</param>
        /// <param name="sz">The <see cref="Size"/> that specifies the numbers to add to the coordinates of pt.</param>
        /// <returns></returns>
        public static PointDouble Add(PointDouble pt, Size sz)
        {
            return new PointDouble(pt.X + sz.Width, pt.Y + sz.Height);
        }

        /// <summary>
        /// 在指定的点的基础上平移
        /// </summary>
        /// <param name="pt">The <see cref="PointDouble"/> to translate.</param>
        /// <param name="sz">The <see cref="SizeF"/> that specifies the numbers to add to the coordinates of pt.</param>
        /// <returns></returns>
        public static PointDouble Add(PointDouble pt, SizeF sz)
        {
            return new PointDouble(pt.X + sz.Width, pt.Y + sz.Height);
        }

        /// <summary>
        /// 在指定的点的基础上平移
        /// </summary>
        /// <param name="pt">The <see cref="PointDouble"/> to translate.</param>
        /// <param name="sz">The <see cref="SizeDouble"/> that specifies the numbers to add to the coordinates of pt.</param>
        /// <returns></returns>
        public static PointDouble Add(PointDouble pt, SizeDouble sz)
        {
            return new PointDouble(pt.X + sz.Width, pt.Y + sz.Height);
        }

        /// <summary>
        /// 在指定的点的基础上平移
        /// </summary>
        /// <param name="pt">The <see cref="PointDouble"/> to translate.</param>
        /// <param name="sz">The <see cref="Size"/> that specifies the numbers to subtract from the coordinates of pt.</param>
        /// <returns></returns>
        public static PointDouble Subtract(PointDouble pt, Size sz)
        {
            return new PointDouble(pt.X - sz.Width, pt.Y - sz.Height);
        }

        /// <summary>
        /// 在指定的点的基础上平移
        /// </summary>
        /// <param name="pt">The <see cref="PointDouble"/> to translate.</param>
        /// <param name="sz">The <see cref="SizeF"/> that specifies the numbers to subtract from the coordinates of pt.</param>
        /// <returns></returns>
        public static PointDouble Subtract(PointDouble pt, SizeF sz)
        {
            return new PointDouble(pt.X - sz.Width, pt.Y - sz.Height);
        }

        /// <summary>
        /// 在指定的点的基础上平移
        /// </summary>
        /// <param name="pt">The <see cref="PointDouble"/> to translate.</param>
        /// <param name="sz">The <see cref="SizeDouble"/> that specifies the numbers to subtract from the coordinates of pt.</param>
        /// <returns></returns>
        public static PointDouble Subtract(PointDouble pt, SizeDouble sz)
        {
            return new PointDouble(pt.X - sz.Width, pt.Y - sz.Height);
        }

        public override bool Equals(object obj)
        {
            if (!(obj is PointDouble))
            {
                return false;
            }
            PointDouble tf = (PointDouble)obj;
            return (((tf.X == X) && (tf.Y == Y))
                && tf.GetType().Equals(GetType()));
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override string ToString()
        {
            return string.Format(CultureInfo.CurrentCulture, "{{X={0}, Y={1}}}", new object[] { this.x, this.y });
        }

    }
}
